package com.ark.frigate.tools.utils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.SocketTimeoutException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeoutException;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;

import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.Consts;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.NoHttpResponseException;
import org.apache.http.StatusLine;
import org.apache.http.client.HttpResponseException;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;

import com.google.common.collect.Maps;

/**
 * 添加标记
 *
 * @author zengweilong
 * @date 3/17/21 5:59 PM
 */
public class HttpClientUtils {

    private static final Logger logger = LoggerFactory.getLogger(HttpClientUtils.class);
    /**
     * 设置连接超时时间，单位毫秒。
     */
    private static final int CONNECTION_TIMEOUT = 1000;
    /**
     * 等待响应超时（读取数据超时）socketTimeout
     */
    private static final int SOCKET_TIMEOUT = 3000;
    /**
     * 设置从connect Manager获取Connection 超时时间，单位毫秒。这个属性是新加的属性，因为目前版本是可以共享连接池的。
     */
    private static final int CONNECTION_REQUEST_TIMEOUT = 2000;
    private static final int DEFAULT_MAX_PER_ROUTE = 300;
    private static final int MAX_TOTAL = 1500;
    private static final CloseableHttpClient CLIENT;
    private static HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = null;

    static {
        SSLContext sslContext = null;
        try {
            sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {

                @Override
                public boolean isTrusted(java.security.cert.X509Certificate[] arg0, String arg1) {

                    return true;
                }
            }).build();

        } catch (Exception e) {
            logger.error("sslContext init error", e);
        }

        final HostnameVerifier hostnameVerifier = NoopHostnameVerifier.INSTANCE;

        SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslContext, hostnameVerifier);
        Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
                .register("http", PlainConnectionSocketFactory.getSocketFactory()).register("https", sslSocketFactory)
                .build();

        PoolingHttpClientConnectionManager connectionManager =
                new PoolingHttpClientConnectionManager(socketFactoryRegistry);
        // 为单路由设置默认最大并发连接数
        connectionManager.setDefaultMaxPerRoute(DEFAULT_MAX_PER_ROUTE);
        // 设置最大并发连接数
        connectionManager.setMaxTotal(MAX_TOTAL);
        // 对超过3秒未活跃的链接进行检查
        connectionManager.setValidateAfterInactivity(3 * 1000);

        RequestConfig requestConfig = RequestConfig.custom()
                /**
                 * 设置等待响应时间
                 */
                .setSocketTimeout(SOCKET_TIMEOUT)
                /**
                 * 设置请求连接时间
                 */
                .setConnectionRequestTimeout(CONNECTION_REQUEST_TIMEOUT)
                /**
                 * 传输超时时间
                 */
                .setConnectTimeout(CONNECTION_TIMEOUT).build();

        CLIENT = HttpClientBuilder.create().setSSLContext(sslContext)
                /**
                 * 写入默认配置
                 */
                .setDefaultRequestConfig(requestConfig)
                /**
                 * 设置连接池管理
                 */
                .setConnectionManager(connectionManager).build();

        clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory(CLIENT);

    }

    private HttpClientUtils() {
    }

    private static String getDefaultEncoding(String defaultEncoding) {

        return StringUtils.isEmpty(defaultEncoding) ? Consts.UTF_8.name() : defaultEncoding;
    }

    /**
     * post Json 默认重试请求3次
     *
     * @param url
     * @param jsonData
     * @param socketTimeout
     *
     * @return
     */
    public static String timeoutRetryPost(String url, String jsonData, int socketTimeout) {
        return timeoutRetryPost(url, jsonData, null, 0, socketTimeout);
    }

    /**
     * post Json 默认重试请求3次
     *
     * @param url
     * @param jsonData
     * @param connectionTimeout
     * @param socketTimeout
     *
     * @return
     */
    public static String timeoutRetryPost(String url, String jsonData, int connectionTimeout, int socketTimeout) {
        return timeoutRetryPost(url, jsonData, null, connectionTimeout, socketTimeout);
    }

    /**
     * post Json 默认重试请求3次
     *
     * @param url
     * @param jsonData
     * @param header
     * @param connectionTimeout
     * @param socketTimeout
     *
     * @return
     */
    public static String timeoutRetryPost(String url, String jsonData, Map<String, String> header,
                                          int connectionTimeout, int socketTimeout) {
        Response response = timeoutRetryPost(url, jsonData, header, 3, connectionTimeout, socketTimeout);
        if (response != null) {
            return response.getContent();
        }
        return null;
    }

    /**
     * post Json 指定重试请求3次 按照默认请求时间
     *
     * @param url
     * @param jsonData
     *
     * @return
     */
    public static String timeoutRetryPost(String url, String jsonData) {

        return timeoutRetryPost(url, jsonData, null);
    }

    /**
     * post Json 指定重试请求3次 按照默认请求时间
     *
     * @param url
     * @param jsonData
     * @param header
     *
     * @return
     */
    public static String timeoutRetryPost(String url, String jsonData, Map<String, String> header) {

        Response response = timeoutRetryPost(url, jsonData, header, 3, CONNECTION_TIMEOUT, SOCKET_TIMEOUT);
        if (response != null) {
            return response.getContent();
        }
        return null;
    }

    /**
     * post Json 指定重试请求次数  按照默认请求时间
     *
     * @param url
     * @param jsonData
     * @param header
     * @param retryTimes
     *
     * @return
     */
    public static Response timeoutRetryPost(String url, String jsonData, Map<String, String> header, int retryTimes) {

        return timeoutRetryPost(url, jsonData, header, retryTimes, CONNECTION_TIMEOUT, SOCKET_TIMEOUT);
    }

    /**
     * 可以设置如果发生socketTimeout,connectionTimeout ,可以设置重试时间 每一次重试都会改变对应的Timeout
     * 如发生SocketTimeOut ,则下一次请求的SocketTimeOut时间为 SocketTimeOut+=(retryTimes+500)
     *
     * @param url
     * @param jsonData
     * @param header
     * @param retryTimes
     *
     * @return
     */
    public static Response timeoutRetryPost(String url, String jsonData, Map<String, String> header, int retryTimes,
                                            int connectionTimeout, int socketTimeout) {

        logger.info(String.format("timeoutRetryPost,url :%s,jsonData :%s,heads:%s ", url, jsonData, header));
        if (retryTimes < 0) {
            throw new IllegalArgumentException("retry times must great than or equal 0");
        }
        HttpPost post = new HttpPost(url);
        Response response = null;
        try {
            response = timeoutRetryRequest(post, jsonData, header, retryTimes, connectionTimeout, socketTimeout);
        } catch (IOException e) {
            logger.error(String.format("timeoutRetryPost error,url:%s,header:%s,param:%s", url,
                    JsonUtils.toJson(header), jsonData), e);
        }
        return response;

    }

    /**
     * 可以设置如果发生socketTimeout,connectionTimeout ,可以设置重试时间 每一次重试都会改变对应的Timeout
     * 如发生SocketTimeOut ,则下一次请求的SocketTimeOut时间为 SocketTimeOut+=(retryTimes+500)
     *
     * @param requestBase
     * @param jsonData
     * @param header
     * @param retryTimes
     *
     * @return
     *
     * @throws IOException
     */
    private static Response timeoutRetryRequest(HttpEntityEnclosingRequestBase requestBase, String jsonData,
                                                Map<String, String> header, int retryTimes, int connectionTimeout,
                                                int socketTimeout) throws IOException {

        Exception ste = null;
        if (connectionTimeout == 0) {
            connectionTimeout = CONNECTION_TIMEOUT;
        }
        if (socketTimeout == 0) {
            socketTimeout = SOCKET_TIMEOUT;
        }

        for (int i = 0; i <= retryTimes; i++) {
            try {
                Response result = interaction(requestBase, jsonData, null, header, socketTimeout, connectionTimeout);
                if (i > 0) {
                    logger.warn("timeoutRetryRequest [{}] retry {} times", requestBase.getURI(), i);
                }
                //如果状态码是 504 OR 408 则进行重试
                if (result.getStatusCode() == HttpStatus.SC_GATEWAY_TIMEOUT
                        || result.getStatusCode() == HttpStatus.SC_REQUEST_TIMEOUT) {
                    ste = new TimeoutException("HttpStatus is " + result.getStatusCode() + " TIMEOUT");
                    connectionTimeout += (i * 500);
                } else {
                    return result;
                }
            } catch (ConnectTimeoutException e) {
                ste = e;
                connectionTimeout += (i * 500);
            } catch (SocketTimeoutException e) {
                ste = e;
                socketTimeout += (i * 500);
            } catch (NoHttpResponseException e) {
                ste = e;
                logger.warn("NoHttpResponseException retry:" + i);
                if (i >= 3) {
                    throw e;
                }

            }
        }
        logger.error(String.format("post [%s] timeout error, retry %s times", requestBase.getURI(), retryTimes), ste);
        return null;
    }

    /**
     * @param requestBase
     * @param jsonData
     * @param defaultEncoding
     * @param headers
     * @param readTimeout
     * @param connectionTimeout
     *
     * @return
     *
     * @throws IOException
     */
    private static Response interaction(HttpEntityEnclosingRequestBase requestBase, String jsonData,
                                        String defaultEncoding, Map<String, String> headers, int readTimeout,
                                        int connectionTimeout)
            throws IOException {

        defaultEncoding = HttpClientUtils.getDefaultEncoding(defaultEncoding);
        CloseableHttpResponse response = null;
        try {
            if (ArrayUtils.isEmpty(requestBase.getAllHeaders())) {
                if (MapUtils.isNotEmpty(headers)) {
                    for (Map.Entry<String, String> entry : headers.entrySet()) {
                        requestBase.setHeader(entry.getKey(), entry.getValue());
                    }
                }
            }
            setHeaderByRequestTraceId(requestBase);
            if (StringUtils.isNotBlank(jsonData)) {
                StringEntity entity = new StringEntity(jsonData, defaultEncoding);
                entity.setContentType(new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));
                requestBase.setEntity(entity);
            }
            response = HttpClientUtils.CLIENT.execute(setConfig(requestBase, readTimeout, connectionTimeout));
            int statusCode = response.getStatusLine().getStatusCode();
            String content = EntityUtils.toString(response.getEntity());
            logger.info(String.format("interaction %s 请求成功,statusCode:%s", requestBase.getURI(), statusCode));
            return new Response(statusCode, content);
        } catch (Exception e) {
            logger.error(String.format("interaction [%s] happens error ", requestBase.getURI()), e);
            throw e;
        } finally {
            if (null != response) {
                try {
                    response.close();
                } catch (IOException e) {
                    logger.error(String.format("关闭输出流 [%s] happens error ", requestBase.getURI()), e);
                }
            }

        }
    }

    private static HttpRequestBase setConfig(HttpRequestBase requestBase, int readTimeout, int connectionTimeout) {

        RequestConfig.Builder configBuilder = requestBase.getConfig() != null ? RequestConfig.copy(requestBase
                .getConfig()) : RequestConfig.custom();
        if (readTimeout > 0) {
            configBuilder.setSocketTimeout(readTimeout);
        }
        if (connectionTimeout > 0) {
            configBuilder.setConnectTimeout(connectionTimeout);
        }
        requestBase.setConfig(configBuilder.build());
        return requestBase;
    }

    /**
     * 请求特定的url提交表单，使用post方法，返回响应的内容
     *
     * @param url
     * @param formData 表单的键值对
     *
     * @return
     */
    public static String post(String url, Map<String, String> formData) {

        return post(url, formData, Maps.newHashMap(), 0);
    }

    /**
     * 请求特定的url提交表单，使用post方法，返回响应的内容
     *
     * @param url
     * @param formData 表单的键值对
     *
     * @return
     */
    public static String post(String url, Map<String, String> formData, int readTimeout) {

        return post(url, formData, Maps.newHashMap(), readTimeout);
    }

    /**
     * 指定headers的post请求
     *
     * @param url
     * @param formData
     * @param headers
     *
     * @return
     */
    public static String post(String url, Map<String, String> formData, Map<String, String> headers) {

        return post(url, formData, headers, 0);
    }

    public static String post(String url, Map<String, String> formData, Map<String, String> headers, int readTimeout) {

        try {
            return postWithTimeoutException(url, formData, null, headers, readTimeout);
        } catch (SocketTimeoutException e) {
            logger.error(String.format("post [%s] timeout", url), e);
            return null;
        }
    }

    /**
     * 请求特定的url提交Json字符串，使用post方法，返回响应的内容
     *
     * @param url
     * @param jsonData
     *
     * @return
     */
    public static String post(String url, String jsonData) {

        return post(url, jsonData, null, null, 0, 0);
    }

    public static String post(String url, String jsonData, int readTimeout) {

        return post(url, jsonData, null, null, readTimeout, 0);
    }

    public static String post(String url, String jsonData, Map<String, String> headers) {

        return post(url, jsonData, null, headers, 0, 0);
    }

    public static String post(String url, String jsonData, Map<String, String> headers, int timeout,
                              int connectionTimeout) {

        return post(url, jsonData, null, headers, timeout, connectionTimeout);
    }

    /**
     * 请求特定的url提交表单，使用post方法，返回响应的内容
     *
     * @param url
     * @param formData        表单的键值对
     * @param defaultEncoding 处理 form encode 的编码，以及作为 contentType 的默认编码
     *
     * @return
     */
    public static String post(String url, Map<String, String> formData, String defaultEncoding, int readTimeout) {

        try {
            return postWithTimeoutException(url, formData, defaultEncoding, null, readTimeout);
        } catch (SocketTimeoutException e) {
            logger.error(String.format("post [%s] timeout error", url), e);
            return null;
        }
    }

    private static String postWithTimeoutException(String url, Map<String, String> formData, String defaultEncoding,
                                                   Map<String, String> headers, int readTimeout)
            throws SocketTimeoutException {

        logger.info(String.format("postWithTimeoutException,url :%s,formData:%s,heads:%s ", url, formData, headers));
        defaultEncoding = HttpClientUtils.getDefaultEncoding(defaultEncoding);

        HttpPost post = new HttpPost(url);
        if (readTimeout > 0) {
            RequestConfig.Builder configBuilder = post.getConfig() != null ? RequestConfig.copy(post.getConfig())
                    : RequestConfig.custom();
            configBuilder.setSocketTimeout(readTimeout);
            post.setConfig(configBuilder.build());
        }
        String content = null;
        List<NameValuePair> nameValues = new ArrayList<NameValuePair>();
        if (formData != null && !formData.isEmpty()) {
            for (Map.Entry<String, String> entry : formData.entrySet()) {
                String value = entry.getValue() == null ? null : entry.getValue();
                nameValues.add(new BasicNameValuePair(entry.getKey(), value));
            }
        }

        if (headers != null) {
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                post.addHeader(entry.getKey(), entry.getValue());
            }
        }
        setHeaderByRequestTraceId(post);
        try {
            UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(nameValues, defaultEncoding);
            post.setEntity(formEntity);
            content = HttpClientUtils.CLIENT.execute(post, new CharSetableResponseHandler(defaultEncoding));
            logger.info(String.format("interaction %s 请求成功,content:%s", url, content));
        } catch (Exception e) {
            logger.error(String.format("post [%s] happens error ", url), e);
        } finally {
            post.releaseConnection();
        }
        return content;
    }

    /**
     * 请求特定的url提交Json字符串，使用post方法，返回响应的内容
     *
     * @param url
     * @param jsonData
     *
     * @return
     */
    public static String post(String url, String jsonData, String defaultEncoding, Map<String, String> headers,
                              int readTimeout, int connectionTimeout) {

        logger.info("Post data map,url = {},params = {}", url, jsonData);
        String content = null;
        HttpPost post = new HttpPost(url);

        if (readTimeout == 0) {
            readTimeout = SOCKET_TIMEOUT;
        }

        if (connectionTimeout == 0) {
            connectionTimeout = CONNECTION_TIMEOUT;
        }

        try {
            Response response = interaction(post, jsonData, defaultEncoding, headers, readTimeout, connectionTimeout);
            logger.info("Post data,response status line = {}", response.getStatusCode());
            if (response != null) {
                content = response.getContent();
            }
        } catch (Exception e) {
            logger.error(String.format("post [%s] happens error ", url), e);
        } finally {
            post.releaseConnection();
        }
        return content;
    }

    public static Response postRestful(String url, String jsonData, String defaultEncoding,
                                       Map<String, String> headers) {

        logger.info("Post data map,url = {},params = {}", url, jsonData);
        HttpPost post = new HttpPost(url);
        try {
            Response response = interaction(post, jsonData, defaultEncoding, headers, 0, 0);
            logger.info("Post data,response status line = {}", response.getStatusCode());
            return response;
        } catch (Exception e) {
            logger.error(String.format("post [%s] happens error ", url), e);
        } finally {
            post.releaseConnection();
        }
        return null;
    }

    public static Response put(String url, String jsonData, Map<String, String> headers) {

        return put(url, jsonData, null, headers);
    }

    /**
     * 请求特定的url提交Json字符串，使用put方法，返回响应的内容
     *
     * @param url
     * @param jsonData
     * @param defaultEncoding
     * @param headers
     *
     * @return
     */
    public static Response put(String url, String jsonData, String defaultEncoding, Map<String, String> headers) {

        Response response = null;
        HttpPut put = new HttpPut(url);
        try {
            response = interaction(put, jsonData, defaultEncoding, headers, 0, 0);
            if (response != null) {
                logger.info("httpClientUtils put response status:{},content:{}", response.getStatusCode(),
                        response.getContent());
            } else {
                logger.info("httpClientUtils put response:null");
            }

        } catch (Exception e) {
            logger.error(String.format("post [%s] happens error ", url), e);
        } finally {
            put.releaseConnection();
        }
        return response;
    }

    /**
     * 请求特定的url，返回响应的内容
     *
     * @param url
     *
     * @return
     */
    public static String get(String url) {

        return get(url, null, 0);
    }

    /**
     * 请求特定的url，返回响应的内容
     *
     * @param url
     * @param readTimeout
     *
     * @return
     */
    public static String get(String url, int readTimeout) {

        return get(url, null, readTimeout);
    }

    /**
     * 请求特定的url，返回响应的内容
     *
     * @param url
     * @param defaultEncoding 如果返回的 contentType 中没有指定编码，则使用默认编码
     * @param readTimeout     : socket timeout
     *
     * @return
     */
    public static String get(String url, String defaultEncoding, int readTimeout) {

        logger.info("get,url:{},defaultEncoding:{},readTimeout:{}", url, defaultEncoding, readTimeout);
        defaultEncoding = HttpClientUtils.getDefaultEncoding(defaultEncoding);
        HttpGet get = new HttpGet(url);
        if (readTimeout > 0) {
            RequestConfig.Builder configBuilder = get.getConfig() != null ? RequestConfig.copy(get.getConfig())
                    : RequestConfig.custom();
            configBuilder.setSocketTimeout(readTimeout);
            get.setConfig(configBuilder.build());
        }
        String content = null;
        try {
            content = HttpClientUtils.CLIENT.execute(get, new CharSetableResponseHandler(defaultEncoding));
            logger.info("get,url:{},content:{}", url, content);
        } catch (Exception e) {
            logger.error(String.format("request [%s] happens error ", url), e);
        } finally {
            get.releaseConnection();
        }
        return content;
    }

    public static String getStream(String url, String defaultEncoding, int readTimeout) {
        logger.info("get,url:{},defaultEncoding:{},readTimeout:{}", url, defaultEncoding, readTimeout);
        HttpGet get = new HttpGet(url);
        if (readTimeout > 0) {
            RequestConfig.Builder configBuilder = get.getConfig() != null ? RequestConfig.copy(get.getConfig())
                    : RequestConfig.custom();
            configBuilder.setSocketTimeout(readTimeout);
            get.setConfig(configBuilder.build());
        }
        StringBuffer result = new StringBuffer(StringUtils.EMPTY);
        try {
            CloseableHttpResponse response = HttpClientUtils.CLIENT.execute(get);
            InputStream stream = response.getEntity().getContent();
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(stream, defaultEncoding));
            String str;
            while ((str = bufferedReader.readLine()) != null) {
                result.append(str);
            }
            bufferedReader.close();
            response.close();
            logger.info("get,url:{},content:{}", url, result);
        } catch (Exception e) {
            logger.error(String.format("request [%s] happens error ", url), e);
        } finally {
            get.releaseConnection();
        }
        return result.toString();
    }

    public static String get(String url, Map<String, String> pramMap, Map<String, String> headsMap) {

        StringBuilder strBuilder = new StringBuilder(url);
        if (MapUtils.isNotEmpty(pramMap)) {
            strBuilder.append("?");
            for (Map.Entry<String, String> entry : pramMap.entrySet()) {
                try {
                    strBuilder.append(entry.getKey()).append("=")
                            .append(URLEncoder.encode(entry.getValue(), "UTF-8")).append("&");
                } catch (UnsupportedEncodingException e) {
                    logger.warn("getClassroomUrl 参数异常{}", entry.getValue());
                    return null;
                }
            }
        }
        url = strBuilder.toString();
        url = url.endsWith("&") ? url.substring(0, url.length() - 1) : url;
        return get(url, headsMap);
    }

    public static String get(String url, Map<String, String> headers) {

        logger.info("get,url:{},headers:{}", url, headers);
        String content = null;
        HttpGet get = new HttpGet(url);
        try {
            if (MapUtils.isNotEmpty(headers)) {
                for (Map.Entry<String, String> entry : headers.entrySet()) {
                    get.setHeader(entry.getKey(), entry.getValue());
                }
            }
            content = HttpClientUtils.CLIENT.execute(get, new CharSetableResponseHandler("UTF-8"));
            logger.info("get,url:{},content:{}", url, content);
        } catch (Exception e) {
            logger.error(String.format("get [%s] happens error ", url), e);
        } finally {
            get.releaseConnection();
        }
        return content;
    }

    private static void setHeaderByRequestTraceId(HttpRequestBase requestBase) {

        String requestId = MDC.get("requestId");
        //String host = requestBase.getURI().getHost();
        if (StringUtils.isNotBlank(requestId)) {
            requestBase.setHeader("X-Request-ID", requestId);
        }
    }

    public static String getWithMap(Map<String, Object> paramMap, String url) {

        String param = null;
        if (paramMap != null) {
            if (MapUtils.isNotEmpty(paramMap)) {
                StringBuffer sb = new StringBuffer("?");
                for (Map.Entry entry : paramMap.entrySet()) {
                    sb.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
                }
                param = sb.toString();
                param = param.substring(0, param.length() - 1);
            }
        }
        logger.info("get url ={}, param = {}", url, param);
        return get(url + param, null);

    }

    public static String putJson(String url, String jsonData, Map<String, String> headers) {

        String content = null;

        try {
            logger.info("put data map,url = {},params = {},headers = {}", url, jsonData, headers);
            Response response = put(url, jsonData, headers);
            logger.info("put data,response status line = {}", response.getStatusCode());
            if (response != null) {
                content = response.getContent();
            }
        } catch (Exception e) {
            HttpClientUtils.logger.error(String.format("put [%s] happens error ", url), e);
        }

        return content;
    }

    /**
     * 实现描述：返回请求的内容，支持默认的字符集，如果httpEntity没有指定的话
     *
     * @author steven
     * @version v1.0.0
     * @see
     * @since 2016/11/16 下午2:51
     */
    private static class CharSetableResponseHandler implements ResponseHandler<String> {

        private final String defaultEncoding;

        public CharSetableResponseHandler(String defaultEncoding) {

            this.defaultEncoding = defaultEncoding;
        }

        @Override
        public String handleResponse(HttpResponse response) throws IOException {

            StatusLine statusLine = response.getStatusLine();
            HttpEntity entity = response.getEntity();
            if (statusLine.getStatusCode() >= 300) {
                EntityUtils.consume(entity);
                throw new HttpResponseException(statusLine.getStatusCode(), statusLine.getReasonPhrase());
            }
            return entity == null ? null : EntityUtils.toString(entity, defaultEncoding);
        }
    }

    public static class Response {

        private int statusCode;
        private String content;

        public Response(int statusCode, String content) {

            this.statusCode = statusCode;
            this.content = content;
        }

        public int getStatusCode() {

            return statusCode;
        }

        public void setStatusCode(int statusCode) {

            this.statusCode = statusCode;
        }

        public String getContent() {

            return content;
        }

        public void setContent(String content) {

            this.content = content;
        }
    }
}